﻿using System;
using System.Collections.Generic;

namespace JianDanLunZhuan
{
    enum E_nodeState
    {
        wait,
        runn,
        finish,
    }
    class LinkNode
    {
        public string linkname;
        public E_nodeState state; //状态
                                  //public  int super; //优先数
        public int ntime; //总需要运行时间
        public int rtime; //已运行时间
                          //private int rtimeMax;
                          //public  int wtime;//已等待时间
        public int arrivetime;//到达时间
                              //public int isAllRepeated;//记录轮转时间
                              // public bool isAllRepeatedFlow;//记录轮转超标
        public bool isInserted;//记录有无进入进程
        public bool isCompleted;//记录有无运行完成

        public LinkNode(string linkname, int ntime)
        {
            this.linkname = linkname;
            this.state = E_nodeState.wait;
            //this.super = super;
            this.ntime = ntime;
            this.rtime = 0;
            //this.wtime = wtime;
            // this.isAllRepeated = 0;
            //this.isAllRepeatedFlow = false;
            this.isInserted = false;
            this.isCompleted = false;
        }
        public LinkNode(string linkname, int ntime, int arrivetime) : this(linkname, ntime)
        {
            this.arrivetime = arrivetime;
        }

        public void GetRunTime(int value)
        {
            this.rtime = value;
        }

        public void DisPlaying()
        {
            Console.WriteLine(linkname + "       " + state + "       " + arrivetime + "       " + ntime + "        " + rtime);
        }

        private void ChooseColor(E_nodeState state)
        {
            switch (state)
            {
                case E_nodeState.wait:
                    Console.ForegroundColor = ConsoleColor.Blue;
                    break;
                case E_nodeState.runn:
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    break;
                case E_nodeState.finish:
                    Console.ForegroundColor = ConsoleColor.Magenta;
                    break;
            }
        }
        public void DrawT(int width_index1, int _height)
        {
            Console.ForegroundColor = ConsoleColor.White;
            Console.SetCursorPosition(width_index1, _height - 12);
            Console.Write(this.linkname);

            for (int i = 0; i < this.rtime; i++)
            {
                Console.SetCursorPosition(width_index1, _height - 13 - i);
                //Console.Write("  ");
                ChooseColor(this.state);
                Console.Write("■");
            }
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            // Console.WriteLine("Hello World!");
            /* LinkNode node1 = new LinkNode("A", 4, 0);
             LinkNode node2 = new LinkNode("B", 3, 1);
             LinkNode node3 = new LinkNode("C", 5, 2);
             LinkNode node4 = new LinkNode("D", 2, 3);
             LinkNode node5 = new LinkNode("E", 4, 4);*/
            /*********************初始化********************************/
            int _width = 50; int _height = 30;
            ConsoleInit(_width, _height);
            List<LinkNode> LInkList =
                new List<LinkNode> { { new LinkNode("A", 4, 0) }, { new LinkNode("B", 3, 1) },{ new LinkNode("C", 5, 2) }, new LinkNode("D", 2, 3),
                { new LinkNode("E", 4, 4) } };
            List<LinkNode> InRunningList = new List<LinkNode>();//进程进行列表


            while (true)
            {
                // LInkList[1].DisPlaying();
                UnChangedeDraw(_width, _height, LInkList, InRunningList);
                ChangedeDraw(_width, _height, LInkList, InRunningList);
            }
        }
        static void ConsoleInit(int _width, int _height)//基础设置
        {
            //光标隐藏
            Console.CursorVisible = false;
            //舞台大小
            Console.SetWindowSize(_width, _height);
            Console.SetBufferSize(_width, _height);
        }

        static void ClearT(int _width, int _height)
        {
            for (int i = 1; i < _height - 11; i++)
            {
                Console.SetCursorPosition(2, i);
                Console.Write("                                       ");
            }
        }


        static void UnChangedeDraw(int _width, int _height, List<LinkNode> LInkList, List<LinkNode> InRunningList)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            for (int i = 0; i < _width; i += 2)
            {
                Console.SetCursorPosition(i, 0);
                Console.Write("■");
                Console.SetCursorPosition(i, _height - 10);
                Console.Write("■");
                Console.SetCursorPosition(i, _height - 1);
                Console.Write("■");
            }
            for (int i = 0; i < _height; i += 1)
            {
                Console.SetCursorPosition(0, i);
                Console.Write("■");
                Console.SetCursorPosition(_width - 2, i);
                Console.Write("■");
            }

            int width_index = (_width - 4) / LInkList.Count - LInkList.Count / 2;

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.SetCursorPosition(width_index, _height - 11);
            Console.Write("■" + "RUNNING" + "   ");
            Console.ForegroundColor = ConsoleColor.Blue;
            Console.Write("■" + "WAITING" + "   ");
            //Console.ForegroundColor = ConsoleColor.Magenta;
            //Console.Write("■" + "FINISHED" );

            Console.ForegroundColor = ConsoleColor.White;
            Console.SetCursorPosition(width_index, _height - 9);//基础信息
            Console.WriteLine("Pname" + "   " + "state" + "   " + "artime" + "   " + "ntime" + "    " + "rtime");

        }

        static void ChangedeDraw(int _width, int _height, List<LinkNode> LInkList, List<LinkNode> InRunningList)
        {
            //bool isOver = false;
            //int SumIndex = 0;
            int NowIndexScence = 1;//第一次回合
            int N = 2;//时间片段
            bool isStartRotate = false;
            int InRunningListInsert = 0;
            int POPindex = -1;
            string POPlinkname;

            #region 第一回合
            for (int index = 0; index < LInkList.Count; index++)
            {
                //到达时间到达0，未插入处理
                if (LInkList[index].arrivetime == 0 && LInkList[index].isInserted == false)
                {

                    LInkList[index].isInserted = true;


                    /****************将未进的新程序放入到 InRunningList**********************/
                    LinkNode tempNode1 = new LinkNode(LInkList[index].linkname, LInkList[index].ntime, LInkList[index].arrivetime);
                    tempNode1.state = E_nodeState.runn;
                    InRunningList.Add(tempNode1);

                    InRunningListInsert++;
                }

                //每个回合减一
                LInkList[index].arrivetime--;
                if (LInkList[index].arrivetime < 0) LInkList[index].arrivetime = 0;

            }
            OUTPutLInkList(_width, _height, InRunningList, LInkList, NowIndexScence, POPindex, POPlinkname = "");//定位，正在跑的进程，回合制,弹出判断
            #endregion


            while (true)
            {
                //回合进行时

                Console.ReadKey(true);//检测输入
                NowIndexScence++;//下一回合

                //**************************对于InRunningList处理(时间片N,限制边界)
                for (int index = 0; index < InRunningList.Count; index++)//对于InRunningList处理
                {
                    //每回合读取一个时间片N
                    if ((InRunningList[index].state == E_nodeState.runn) && (InRunningList[index].isCompleted == false))
                    {
                        InRunningList[index].rtime += N;
                    }


                    //限制边界
                    if (InRunningList[index].rtime >= InRunningList[index].ntime)
                    {
                        InRunningList[index].rtime = InRunningList[index].ntime;
                        InRunningList[index].isCompleted = true;
                        InRunningList[index].state = E_nodeState.finish;

                        POPindex = index;
                        POPlinkname = InRunningList[index].linkname;

                    }

                }

                /******************************第一次轮转*****************************************************/

                if (InRunningListInsert == LInkList.Count) isStartRotate = true;
                //**************第一次轮转，uncompleted全部插入
                // bool isAllRotate = true;//??
                if (isStartRotate)
                {
                    LinkNode tempNode1 =
                        new LinkNode(InRunningList[InRunningList.Count - 1].linkname, InRunningList[InRunningList.Count - 1].ntime, InRunningList[InRunningList.Count - 1].arrivetime);
                    tempNode1.state = E_nodeState.runn;
                    tempNode1.GetRunTime(InRunningList[InRunningList.Count - 1].rtime);


                    InRunningList.Add(tempNode1);//扩容
                    for (int index = InRunningList.Count - 2; index > 0; index--)//将第一个放置于最后，依次向上
                    {
                        InRunningList[index] = InRunningList[index - 1];
                        InRunningList[index].state = E_nodeState.wait;
                    }
                    InRunningList[0] = tempNode1;
                    InRunningList.RemoveAt(InRunningList.Count - 1);
                }

                //******************************对于LInkList处理(未进的新程序)
                for (int index = 0; index < LInkList.Count; index++)//对于LInkList处理
                {
                    //到达时间到达0，未插入处理
                    if (LInkList[index].arrivetime == 0 && LInkList[index].isInserted == false)
                    {

                        LInkList[index].isInserted = true;

                        /****************将未进的新程序放入到 InRunningList**********************/
                        LinkNode tempNode1 = new LinkNode(LInkList[index].linkname, LInkList[index].ntime, LInkList[index].arrivetime);
                        tempNode1.state = E_nodeState.runn;
                        InRunningList.Add(tempNode1);
                        if (InRunningList.Count <= LInkList.Count)//判断有无剩余的完全插入？？
                        {
                            for (int i = InRunningList.Count - 1; i > 0; i--)
                            {
                                InRunningList[i] = InRunningList[i - 1];
                                InRunningList[i].state = E_nodeState.wait;
                            }
                            InRunningList[0] = tempNode1;
                        }
                        InRunningListInsert++;
                    }

                    //每个回合减一
                    LInkList[index].arrivetime--;
                    if (LInkList[index].arrivetime < 0) LInkList[index].arrivetime = 0;
                }

                /**********************清除IsComplete***********************/
                for (int index = 0; index < InRunningList.Count; index++)//对于InRunningList处理,删除
                {
                    if (InRunningList[index].isCompleted == true)
                    {
                        InRunningList.RemoveAt(index);
                    }
                }


                OUTPutLInkList(_width, _height, InRunningList, LInkList, NowIndexScence, POPindex, POPlinkname);//定位，正在跑的进程，回合制,弹出判断

                POPindex = -1;
            }
            //Console.ReadKey(true);//检测输入
        }

        private static void OUTPutLInkList(int _width, int _height, List<LinkNode> InRunningList, List<LinkNode> LInkList, int NowIndex, int POPindex, string POPlinkname)
        {
            #region 依次画出InRunningList的数值
            Console.ForegroundColor = ConsoleColor.White;
            int width_index = (_width - 4) / LInkList.Count - LInkList.Count / 2;

            for (int j = 0; j < InRunningList.Count; j++)
            {
                Console.SetCursorPosition(width_index, _height - 8 + j);
                InRunningList[j].DisPlaying();
                Console.SetCursorPosition(width_index, _height - 8 + j + 1);
                Console.Write("                                     ");
            }

            Console.SetCursorPosition(width_index, _height - 8 + LInkList.Count + 1);
            Console.Write("                                     ");
            Console.SetCursorPosition(width_index, _height - 8 + LInkList.Count + 1);
            Console.WriteLine("PROCESSING:" + NowIndex);


            if (POPindex != -1)
            {
                Console.SetCursorPosition(_width / 2, _height - 8 + LInkList.Count + 1);
                Console.WriteLine("FINISHED P:" + POPlinkname);
            }

            #endregion

            //***********************************?
            #region 可变方块测绘
            int width_index1 = (_width - 4) / LInkList.Count - LInkList.Count / 2;
            ClearT(_width, _height);
            for (int i = 0; i < InRunningList.Count; i++)
            {
                InRunningList[i].DrawT(width_index1, _height);

                width_index1 += (_width - 4) / LInkList.Count;
            }
            #endregion

        }
    }
}
